using System.Reflection;
using FreeSql;
using KrasDD.Attributes;
using KrasDD.Events;
using KrasDD.Models;
using KrasDD.Services.Interfaces;

namespace KrasDD.Services.Implementations
{
    public class ServerEventHandler : IEventHandler
    {
        private readonly IFreeSql _freeSql;
        private readonly IMethodService _methodService;

        public ServerEventHandler(IFreeSql freeSql, IMethodService methodService)
        {
            _freeSql = freeSql;
            _methodService = methodService;
        }

        public async Task<T> HandleEventAsync<T>(string eventType, T entity)
            where T : AppBaseEntity
        {
            // 1. 查找相关的SERVER_EVENT记录
            var itemTypeAttribute =
                entity.GetType().GetCustomAttributes(typeof(ItemTypeAttribute)).FirstOrDefault()
                as ItemTypeAttribute;
            var sourceId = itemTypeAttribute?.Id ?? entity.GetType().Name;

            var serverEvents = await _freeSql
                .Select<SERVER_EVENT>()
                .Where(se => se.EVENT_TYPE == eventType && se.SOURCE_ID == sourceId)
                .ToListAsync();

            foreach (var serverEvent in serverEvents)
            {
                if (!string.IsNullOrEmpty(serverEvent.RELATED_ID))
                {
                    // 2. 获取对应的METHOD
                    var method = await _methodService.GetByIdAsync(serverEvent.RELATED_ID);
                    if (method != null && !string.IsNullOrEmpty(method.METHOD_CODE))
                    {
                        // 3. 创建KrasServerEvent对象
                        var krasEvent = new KrasServerEvent
                        {
                            EventType = eventType,
                            ID = entity.ID,
                            ItemType = entity.GetType().Name,
                            CustomerParms = entity,
                        };

                        try
                        {
                            // 4. 执行METHOD_CODE
                            var result = AppContainer.CallMethod(method, krasEvent);

                            // 5. 如果返回值是传入的实体类型，则更新实体
                            if (result is T resultEntity)
                            {
                                entity = resultEntity;
                            }
                        }
                        catch (Exception ex)
                        {
                            // 记录执行错误，但不影响主流程
                            Console.WriteLine(
                                $"Error executing method {method.NAME} for event {eventType}: {ex.Message}"
                            );
                        }
                    }
                }
            }

            return entity;
        }
    }
}
